home *** CD-ROM | disk | FTP | other *** search
- /*
- * Copyright (C) 1994, Silicon Graphics, Inc.
- * All Rights Reserved.
- *
- * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
- * the contents of this file may not be disclosed to third parties, copied or
- * duplicated in any form, in whole or in part, without the prior written
- * permission of Silicon Graphics, Inc.
- *
- * RESTRICTED RIGHTS LEGEND:
- * Use, duplication or disclosure by the Government is subject to restrictions
- * as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
- * and Computer Software clause at DFARS 252.227-7013, and/or in similar or
- * successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
- * rights reserved under the Copyright Laws of the United States.
- */
- #include "sw.h"
- #include "extern.h"
- #include "sound.h"
- #include "control.h"
- #include <stdio.h>
- #include <stream.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <fcntl.h>
- #include <string.h>
- #include <audio.h>
- #include <audiofile.h>
-
- #define SAMPLERATE 16000
- #define SAMPSPERSEC (SAMPLERATE * 2)
-
- static int audioAvailable = FALSE;
- static ALport audioPort;
- static ALconfig audioConfig;
- static long oldOutputRate;
- static short* soundSamples[LastSound];
- static long soundNumSamples[LastSound];
- static short* soundBuffer;
- static long lastSamplesLeft;
- static long bufferFullSize, bufferHalfSize;
- static long headSample, tailSample;
- static int playedExplosion;
- static float explosionVolume;
- static long seekingSamplesLeft;
-
- extern int isPaused();
-
- static int readSound(Sound s, const char* dir, const char* name)
- {
- soundSamples[int(s)] = NULL;
- soundNumSamples[int(s)] = 0;
-
- // make file name
- char fn[256];
- sprintf(fn, "%s/%s", dir, name);
-
- // open file
- int fd = open(fn, O_RDONLY);
- if (fd < 0) {
- cerr << fn << ": can't open file\n";
- return FALSE;
- }
-
- // check format
- switch (AFidentifyfd(fd)) {
- case AF_FILE_AIFFC:
- case AF_FILE_AIFF:
- break;
- default:
- cerr << fn << ": not AIFF or AIFF-C\n";
- return FALSE;
- }
-
- // open file
- AFfilehandle f = AFopenfd(fd, "r", AF_NULL_FILESETUP);
- if (f == AF_NULL_FILEHANDLE) {
- cerr << fn << ": can't open file\n";
- return FALSE;
- }
-
- // check that it's the right type
- if (AFgetchannels(f, AF_DEFAULT_TRACK) != 2) {
- cerr << fn << ": wrong number of channels (!=2)\n";
- AFclosefile(f);
- return FALSE;
- }
- long fmt, width;
- AFgetsampfmt(f, AF_DEFAULT_TRACK, &fmt, &width);
- if (width != 16) {
- cerr << fn << ": wrong resolution (!=16 bits/sample)\n";
- AFclosefile(f);
- return FALSE;
- }
-
- // find length of sound and make buffer
- long frames = AFgetframecnt(f, AF_DEFAULT_TRACK) * 2;
- soundSamples[int(s)] = new short[frames * 2];
-
- // read sound into buffer
- frames = AFreadframes(f, AF_DEFAULT_TRACK, soundSamples[int(s)], frames);
- soundNumSamples[int(s)] = frames * 2;
-
- // quiet down the sound
- for (long i = 0; i < soundNumSamples[int(s)]; i++)
- soundSamples[int(s)][i] >>= 2;
-
- // close file
- AFclosefile(f);
-
- return TRUE;
- }
-
- static void deleteSounds()
- {
- for (int i = 0; i < int(LastSound); i++)
- delete[] soundSamples[i];
- }
-
- int openSound(const char* dir)
- {
- if (ALqueryparams(AL_DEFAULT_DEVICE, NULL, 0) == 0)
- return FALSE;
-
- // get old sampling rate
- long outRateBuf[2];
- outRateBuf[0] = AL_OUTPUT_RATE;
- ALgetparams(AL_DEFAULT_DEVICE, outRateBuf, 2);
- oldOutputRate = outRateBuf[1];
-
- // set new sampling rate
- outRateBuf[0] = AL_OUTPUT_RATE;
- outRateBuf[1] = SAMPLERATE;
- ALsetparams(AL_DEFAULT_DEVICE, outRateBuf, 2);
-
- // read in audio files
- readSound(ExplosionSound, dir, "explosion.aiff");
- readSound(KilledSound, dir, "killed.aiff");
- readSound(SeekingSound, dir, "seeking.aiff");
- readSound(LockOnSound, dir, "lockon.aiff");
- readSound(GrabSound, dir, "grab.aiff");
- readSound(DropSound, dir, "drop.aiff");
- readSound(EnemyGrabSound, dir, "flag_alert.aiff");
- readSound(FlagWonSound, dir, "flag_won.aiff");
- readSound(FlagLostSound, dir, "flag_lost.aiff");
- readSound(MissileSound, dir, "missile.aiff");
- readSound(LaserSound, dir, "laser.aiff");
-
- // find longest sound
- bufferHalfSize = 0;
- for (int i = 0; i < int(LastSound); i++)
- if (soundNumSamples[i] > bufferHalfSize)
- bufferHalfSize = soundNumSamples[i];
- bufferFullSize = 2 * bufferHalfSize;
-
- // make local buffer for adding up sounds
- soundBuffer = new short[bufferFullSize];
- if (!soundBuffer) {
- deleteSounds();
- return FALSE;
- }
-
- // configure port
- audioConfig = ALnewconfig();
- ALsetqueuesize(audioConfig, 2 * SAMPSPERSEC * 2);
- ALsetwidth(audioConfig, AL_SAMPLE_16);
- ALsetchannels(audioConfig, AL_STEREO);
-
- // open port
- audioPort = ALopenport("swport", "w", audioConfig);
- if (!audioPort) { // can't open port
- delete[] soundBuffer;
- deleteSounds();
- ALfreeconfig(audioConfig);
- return FALSE;
- }
-
- soundReset();
- audioAvailable = TRUE;
- return TRUE;
- }
-
- void closeSound()
- {
- if (!audioAvailable) return;
-
- // close port
- ALcloseport(audioPort);
-
- // free configuration
- ALfreeconfig(audioConfig);
-
- // set back to old sampling rate
- long outRateBuf[2];
- outRateBuf[0] = AL_OUTPUT_RATE;
- outRateBuf[1] = oldOutputRate;
- ALsetparams(AL_DEFAULT_DEVICE, outRateBuf, 2);
-
- // free sample buffers
- delete[] soundBuffer;
- deleteSounds();
-
- // can't play sounds anymore
- audioAvailable = FALSE;
- }
-
- int hasSound()
- {
- return audioAvailable;
- }
-
- void soundReset()
- {
- headSample = 0;
- tailSample = headSample;
- lastSamplesLeft = 0;
- seekingSamplesLeft = 0;
- playedExplosion = FALSE;
- }
-
- void soundAdvance(float dt)
- {
- if (!audioAvailable) return; // no audio
- if (headSample == tailSample) return; // nothing to play
-
- // find how many samples left in port
- long samplesLeft = ALgetfilled(audioPort);
- if (samplesLeft > long(1.25*dt*SAMPSPERSEC))
- return; // not empty enough yet
-
- // write more samples and move fill point
- long samplesUsed = lastSamplesLeft - samplesLeft;
- long samplesPlay = long(2.5*dt*SAMPSPERSEC) & ~1;
- if (samplesPlay > ALgetfillable(audioPort)) { // will block
- soundReset(); // just give up and start over
- }
- else if (samplesPlay > tailSample-headSample) { // will empty local buffer
- samplesPlay = tailSample - headSample;
- ALwritesamps(audioPort, soundBuffer + headSample, samplesPlay);
- headSample = tailSample = 0;
- seekingSamplesLeft = 0;
- }
- else {
- ALwritesamps(audioPort, soundBuffer + headSample, samplesPlay);
- // if past mid-point of local buffer, shift samples to beginning of buffer
- if ((headSample += samplesPlay) >= bufferHalfSize) {
- memmove(soundBuffer, soundBuffer + headSample,
- int(tailSample - headSample));
- tailSample -= headSample;
- headSample = 0;
- }
- }
- lastSamplesLeft = samplesLeft + samplesPlay;
-
- // update local flags
- playedExplosion = FALSE;
- if ((seekingSamplesLeft -= samplesUsed) < 0)
- seekingSamplesLeft = 0;
- }
-
- void soundPlay(Sound s, float volume)
- {
- if (!audioAvailable) return;
- if (isPaused()) return;
- if (soundDial() == SoundOff) return;
- if (soundDial() == SoundWarnings &&
- (s == ExplosionSound ||
- s == KilledSound ||
- s == GrabSound ||
- s == DropSound ||
- s == FlagWonSound ||
- s == FlagLostSound))
- return;
- if (soundNumSamples[int(s)] == 0) return; // empty sound
-
- if (s == ExplosionSound) {
- // limit the number of explosions played simultaneously
- if (playedExplosion && volume < 2.0*explosionVolume) return;
- playedExplosion = TRUE;
- explosionVolume = volume;
- }
- else if (s == SeekingSound) {
- // play seeking repeatedly (but not on top of itself)
- if (seekingSamplesLeft > 0) return;
- seekingSamplesLeft += soundNumSamples[int(s)];
- }
-
- long c = soundNumSamples[int(s)];
- short* b = soundSamples[int(s)];
- short *sp = soundBuffer + headSample;
-
- // clear out any samples that we'll touch that haven't been touched yet
- if (headSample + c > tailSample) {
- long i = tailSample;
- tailSample = headSample + c;
- for (; i < tailSample; i++)
- soundBuffer[i] = 0;
- }
-
- if (volume == 1.0) { // direct copy
- for (long i = 0; i < c; i++)
- *sp++ += *b++;
- }
- else { // scaled copy
- for (long i = 0; i < c; i++)
- *sp++ += short(volume * float(*b++));
- }
- }
-